package com.jelly.config.shiro;

import com.jelly.common.constant.ShiroConstant;
import com.jelly.common.util.SerializeUtils;
import com.jelly.config.redis.RedisManager;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.springframework.beans.factory.annotation.Value;

import java.util.concurrent.atomic.AtomicInteger;

public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher {

    private RedisManager redisManager;

    private String keyPrefix = ShiroConstant.SHIROREDISLOGINCOUNT;

    @Value("${redis.user.count}")
    private int maxRetryCount;

    @Value("${redis.user.expire}")
    private int expire;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        String username = keyPrefix + token.getPrincipal();

        AtomicInteger retryCount = (AtomicInteger) SerializeUtils.deserialize(redisManager.get(username.getBytes()));

        if (null == retryCount) {
            retryCount = new AtomicInteger(0);
        }else {
            retryCount.set(retryCount.incrementAndGet());
        }

        redisManager.set(username.getBytes(), SerializeUtils.serialize(retryCount),expire);

        if (retryCount.get() >= maxRetryCount) {
            throw new ExcessiveAttemptsException("该账号登录错误次数超过5次请稍后重试");
        }

        boolean matches = super.doCredentialsMatch(token, info);

        if (matches) {

            redisManager.del(username.getBytes());

        }

        return matches;

    }

    public void setRedisManager(RedisManager redisManager) {
        this.redisManager = redisManager;
    }

    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }

    public void setMaxRetryCount(int maxRetryCount) {
        this.maxRetryCount = maxRetryCount;
    }

    public void setExpire(int expire) {
        this.expire = expire;
    }

}
